﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace Mimoza.SystemPlugin
{
    public class ExecutePlugin : Mimoza.PluginLayer.IExecutePlugin
    {
        const int PASSWORD_STATUS_ACTIVE = 1;
        const int PASSWORD_STATUS_SCREENSAVERPROTECT = 2;

        [DllImport("coredll.dll")]
        private static extern int SetPasswordStatus(UInt32 dwStatus,
            [MarshalAs(UnmanagedType.LPWStr)]string lpszPassword);


        [DllImport("coredll.dll")]
        private static extern int SetPassword(
            [MarshalAs(UnmanagedType.LPWStr)]string lpszOldPassword,
            [MarshalAs(UnmanagedType.LPWStr)]string lpszNewPassword);

        [DllImport("coredll.dll", CharSet = CharSet.Auto)]
        private static extern int SetUserData(byte[] lpbUserData, UInt32 dwDataSize);

        private void StorDataInRegistry(string data)
        {
            using (RegistryKey key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Mimoza", true))
            {
                if (key != null)
                {
                    key.SetValue("SystemPlugin", data);
                }
            }
        }
        #region IExecutePlugin Members

        public string PluginId
        {
            get { return this.ToString(); }
        }

        public void Add(Mimoza.ObjectLayer.Policy policy)
        {
            Add(policy, GetData(policy.Data));
            StorDataInRegistry(policy.Data);
        }

        public void Remove(Mimoza.ObjectLayer.Policy policy)
        {
            Remove(policy, GetData(policy.Data));
            StorDataInRegistry("");
        }

        public void Update(Mimoza.ObjectLayer.Policy policy)
        {
            Update(policy, GetData(policy.Data));
            StorDataInRegistry(policy.Data);
        }

        #endregion

        void Add(Mimoza.ObjectLayer.Policy policy, SystemPluginData data)
        {
            Trace("Add", policy, data);
            ApplySystemPolicy(policy, data);
        }

        void Update(Mimoza.ObjectLayer.Policy policy, SystemPluginData data)
        {
            Trace("Update", policy, data);
            ApplySystemPolicy(policy, data);
        }

        void Remove(Mimoza.ObjectLayer.Policy policy, SystemPluginData data)
        {
            Trace("Remove", policy, data);
        }

        void ApplySystemPolicy(Mimoza.ObjectLayer.Policy policy, SystemPluginData data)
        {
            NeedToRestart = false;

            SetTransportActivity(data.NetworkActivityLevel);

            ApplyNewServiceName(data);
            
            //Disabled becouse OLD password is requried and this code can't work properly without old password
            //ApplyPasswordProtection(data);

            ApplyServiceActivity(data);

            ApplyShortcuts(data);

            if (NeedToRestart) Mimoza.PluginLayer.PluginResultStore.PutRestartResult();
        }

        bool NeedToRestart
        {
            get;
            set;
        }
            
        void Trace(string operationName, Mimoza.ObjectLayer.Policy policy, SystemPluginData data)
        {
            Common.Logger.Log.Info("Mimoza.SystemPlugin.ExecutePlugin." + operationName + 
                " Name - '" + policy.Name + "'.");
        }

        void SetTransportActivity(int networkActivityLevel)
        {
            double cooficent = 1 / ((double)networkActivityLevel / (double)SystemPluginData.c_DefaultNetworkActivityLevel);
            int connectTimeout = (int)(Mimoza.Common.GlobalSettings.c_DefaultPingTimeout * cooficent);

            Mimoza.AgentLayer.Settings settings = Mimoza.AgentLayer.Settings.GlobalSettings;

            if (settings!=null && settings.CreateConnectionPeriod != connectTimeout)
            {
                Common.Logger.Log.Info("Mimoza.SystemPlugin.ExecutePlugin.SetTransportActivity connectionTimeout - {0} newTimeout - {1}." +
                    settings.CreateConnectionPeriod, connectTimeout);

                settings.CreateConnectionPeriod = connectTimeout;
                Mimoza.AgentLayer.Settings.Save(settings);
            }
        }

        void ApplyServiceActivity(SystemPluginData data)
        {
            Common.Logger.Log.Info("Mimoza.SystemPlugin.ExecutePlugin.ApplyServiceActivity data.IsServiceDisable - {0}." +
                    data.IsServiceDisable);

            if (data.IsServiceDisable)
            {
                Mimoza.AgentLayer.Settings settings = Mimoza.AgentLayer.Settings.GlobalSettings;

                if (settings != null)
                {
                    settings.ServerHost = "";
                    settings.HostId = Guid.NewGuid().ToString();
                    settings.ServerAddr = "";
                    settings.BroadcastTransportPort = 0;

                    Mimoza.AgentLayer.Settings.Save(settings);

                    Mimoza.AgentLayer.Configuration.GlobalConfiguration.ReStart();
                }
            }
            else
            {
                Mimoza.AgentLayer.Settings settings = Mimoza.AgentLayer.Settings.GlobalSettings;

                if (settings != null && settings.BroadcastTransportPort == 0)
                {
                    settings.Init();

                    Mimoza.AgentLayer.Settings.Save(settings);

                    Mimoza.AgentLayer.Configuration.GlobalConfiguration.ReStart();
                }
            }
        }

        void ApplyNewServiceName(SystemPluginData data)
        {
            if (data.IsNewServiceSelected)
            {
                Common.Logger.Log.Info("Mimoza.SystemPlugin.ExecutePlugin.ApplyNewServiceName newServiceLocation - {0}." +
                    data.NewServiceAddress);

                Mimoza.AgentLayer.Settings settings = Mimoza.AgentLayer.Settings.GlobalSettings;

                if (settings != null)
                {
                    settings.ServerHost = "";
                    settings.HostId = Guid.NewGuid().ToString();
                    settings.ServerAddr = data.NewServiceAddress;

                    Mimoza.AgentLayer.Settings.Save(settings);

                    Mimoza.AgentLayer.Configuration.GlobalConfiguration.ReStart();
                }
            }
        }

        void ApplyPasswordProtection(SystemPluginData data)
        {
            //if (data.HasProtectionOnStartup || data.HasProtectionOnScreenSaver)
            {
                Common.Logger.Log.Info("Mimoza.SystemPlugin.ExecutePlugin.ApplyPasswordProtection pass - {0} onStartup - {1} onScreen - {2}." +
                    data.Password, data.HasProtectionOnStartup, data.HasProtectionOnScreenSaver);

                UInt32 flags = 0;
                if (data.Password != null && data.Password.Length != 0)
                {
                    flags = PASSWORD_STATUS_ACTIVE;
                    if (data.HasProtectionOnScreenSaver) flags |= PASSWORD_STATUS_SCREENSAVERPROTECT;
                }
#if WindowsCE
                SetPasswordStatus(flags, data.Password);
#endif            
                //NeedToRestart = true;
            }
        }

        const string constDefaultRDP = "\\Default RDP.lnk";
        const string constInternetExplrerLink = "\\Internet Explorer.lnk";

        const string MyDeviceID = "{000214A0-0000-0000-C000-000000000046}";
        const string MyDeviceVal = "My Device";
        const string RecycleBinID = "{000214A1-0000-0000-C000-000000000046}";
        const string RecycleBinVal = "Recycle Bin";

        void ApplyShortcuts(SystemPluginData data)
        {
            string desktop = "";
            using (RegistryKey key = Registry.LocalMachine.OpenSubKey("SYSTEM\\Explorer\\Shell Folders", false))
            {
                if (key == null)
                {
                    return;
                }
                desktop = key.GetValue("Desktop").ToString();
            }

            using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Explorer\\Desktop", true))
            {
                bool MyDeviceIDIsExist = false;
                bool RecycleBinIDIsExist = false;

                foreach ( string val in key.GetValueNames())
                {
                    if ( val == MyDeviceID )
                    {
                        MyDeviceIDIsExist = true;
                    }

                    if (val == RecycleBinID)
                    {
                        RecycleBinIDIsExist = true;
                    }
                }

                if ((data.ShownShortcutBitMask & ShortcutBitmask.MyComputer) != 0 && !MyDeviceIDIsExist)
                {
                    key.SetValue(MyDeviceID, MyDeviceVal, RegistryValueKind.String);
                    NeedToRestart = true;
                }

                if ((data.ShownShortcutBitMask & ShortcutBitmask.MyComputer) == 0 && MyDeviceIDIsExist)
                {
                    key.DeleteValue(MyDeviceID, false);
                    NeedToRestart = true;
                }

                if ((data.ShownShortcutBitMask & ShortcutBitmask.RecycleBin) != 0 && !RecycleBinIDIsExist)
                {
                    key.SetValue(RecycleBinID, RecycleBinVal, RegistryValueKind.String);
                    NeedToRestart = true;
                }

                if ((data.ShownShortcutBitMask & ShortcutBitmask.RecycleBin) == 0 && RecycleBinIDIsExist)
                {
                    key.DeleteValue(RecycleBinID, false);
                    NeedToRestart = true;
                }

            }

            if ((data.ShownShortcutBitMask & ShortcutBitmask.InternetExplorer) != 0)
            {
                using (TextWriter tw = new StreamWriter(desktop + constInternetExplrerLink, false, Encoding.ASCII))
                {
                    tw.Write("22#\\Windows\\iesample.exe");
                }
            }
            else
            {
                if (File.Exists(desktop + constInternetExplrerLink))
                {
                    File.Delete(desktop + constInternetExplrerLink);
                }
            }

            if ((data.ShownShortcutBitMask & ShortcutBitmask.DefaultRDP) != 0)
            {
                using (TextWriter tw = new StreamWriter(desktop + constDefaultRDP, false, Encoding.ASCII))
                {
                    tw.Write("19#\\Windows\\cetsc.exe");
                }
            }
            else
            {
                if (File.Exists(desktop + constDefaultRDP))
                {
                    File.Delete(desktop + constDefaultRDP);
                }
            }
        }

        SystemPluginData GetData(string data)
        {
            return SystemPluginData.Deserialize(data);
        }
    }
}
